package cn.zglbk.network.context;
import cn.zglbk.network.channel.AbstractGameChannelHandlerContext;
import cn.zglbk.network.param.*;
import cn.zglbk.utils.SerializableUtils;
import com.google.protobuf.Message;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.Promise;

public class GatewayMessageContext<T> implements IGameChannelContext {
    private GameMessagePackage message;
    private AbstractGameChannelHandlerContext ctx;
   private T dataManager;

    // 这里面的Player和PlayerManager参数是为了兼容前面的测试代码，在实际应用中可以去掉
    public GatewayMessageContext(T dataManager, GameMessagePackage message, AbstractGameChannelHandlerContext ctx) {
        this.message = message;
        this.ctx = ctx;

        this.dataManager = dataManager;
    }

    public T getDataManager() {
        return dataManager;
    }

    @Override
    public void sendMessage(Message.Builder builder) {
        if (builder != null) {
            wrapResponseMessage(builder);
            ctx.writeAndFlush(message);
        }
    }

    @Override
    public void sendError(Message.Builder builder) {
        if (builder != null) {
            wrapResponseMessage(builder);
            message.getHeader().setErrorCode(34);
            ctx.writeAndFlush(message);
        }
    }

    private void wrapResponseMessage(com.google.protobuf.Message.Builder builder) {
        this.message.setBody(SerializableUtils.toByteArray(builder));
    }
    /**
     * 将同一条消息广播给本服的所有人
     * <p>Description: </p>
     * @param builder
     * @author wgs 
     * @date  2019年7月25日 下午9:27:28
     *
     */
    public void broadcastMessage(int serviceId,int messageId,Message.Builder builder) {
        if (builder != null) {
            ctx.gameChannel().getEventDispathService().broadcastMessage(broadcastMessageWarapping(serviceId,messageId,builder));
        }
    }
    public void broadcastMessage(int serviceId,int messageId,Message.Builder builder,long...playerIds) {
        if(builder != null){
            GameMessagePackage messagePackage = broadcastMessageWarapping(serviceId, messageId, builder);
            ctx.gameChannel().getEventDispathService().broadcastMessage(messagePackage,playerIds);
        }
    }
    public void broadcastMessage(GameMessagePackage p){
        if(p != null){
            ctx.gameChannel().getEventDispathService().broadcastMessage(p);
        }
    }
    private GameMessagePackage broadcastMessageWarapping(int serviceId,int messageId,Message.Builder builder){
        GameMessagePackage messagePackage = new GameMessagePackage();
        GameMessageHeader header = new GameMessageHeader();
        header.setMesasageType(EnumMesasageType.BROADCAST);
        header.setServiceId(serviceId);
        header.setMessageId(messageId);
        messagePackage.setHeader(header);
        messagePackage.setBody(SerializableUtils.toByteArray(builder));
        return messagePackage;
    }
    /**
     * 
     * <p>
     * Description:如果发送的请求，需要处理返回值，就使用这个方法发送rpc请求
     * </p>
     * 
     * @param rpcRequest
     * @param callback
     * @return
     * @author wgs
     * @date 2019年6月17日 下午5:16:09
     *
     */
    public Future<IGameMessage> sendRPCMessage(IGameMessage rpcRequest, Promise<IGameMessage> callback) {
        if (rpcRequest != null) {
            rpcRequest.getHeader().setPlayerId(ctx.gameChannel().getPlayerId());
            ctx.writeRPCMessage(rpcRequest, callback);
        } else {
            throw new NullPointerException("RPC消息不能为空");
        }
        return callback;
    }

    /**
     * <p>
     * Description:如果发送的rpc请求不需要处理返回结果，就使用这个方法
     * </p>
     * 
     * @param rpcRequest
     * @author wgs
     * @date 2019年6月17日 下午5:16:31
     *
     */
    public void sendRPCMessage(IGameMessage rpcRequest) {
        if (rpcRequest != null) {
            ctx.writeRPCMessage(rpcRequest, null);
        } else {
            throw new NullPointerException("RPC消息不能为空");
        }
    }

    /**
     * <p>
     * Description:向某个playerId的GameChannel中发送一个事件
     * </p>
     * 
     * @param event
     * @param promise
     * @param playerId
     * @author wgs
     * @date 2019年6月9日 下午5:05:50
     *
     */
    private  <K> Future<K> sendUserEvent(K event, Promise<K> promise, long playerId) {
        ctx.gameChannel().getEventDispathService().fireUserEvent(playerId, event, promise);
        return promise;
    }
    public <K> void sendUserEvent(K event,long playerId,GatewayMessageCallBack<K> callBack){
        sendUserEvent(event,newPromise(),playerId).addListener((GenericFutureListener<Future<K>>) future -> {
            if(future.isSuccess()){
                K k = future.get();
                callBack.action(k, k != null);
            }else {
                callBack.action(null,false);
            }
        });
    }
//    /**
//     * 检查用户是都在线
//     * @param promise
//     * @param playerId
//     * @return
//     */
//    public Future<Object> checkUser( Promise<Object> promise, long playerId) {
//        ctx.gameChannel().getEventDispathService().checkUser(playerId, promise);
//        return promise;
//    }
    public <E> DefaultPromise<E> newPromise() {
        return new DefaultPromise<>(ctx.executor());
    }
    public DefaultPromise<IGameMessage> newRPCPromise() {
        return new DefaultPromise<>(ctx.executor());
    }
    @SuppressWarnings("unchecked")
    @Override
    public <E> E getRequest() {
        return (E) this.message;
    }

    @Override
    public String getRemoteHost() {
        return this.message.getHeader().getAttribute().getClientIp();
    }



    @Override
    public long getPlayerId() {
        return this.message.getHeader().getPlayerId();
    }


}
